/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c) 2002, GeoVISTA Center
 * Licensed under Simplified BSD License
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
 *
 * @original author: jin Chen 
 * @author: jin Chen 
 * @date: Nov 12, 2007$
 * @version: 1.0
 */
package edu.psu.geovista.app.vit.pub.components.sts;

import edu.psu.geovista.app.vit.pub.utils.VitUtils;
import edu.psu.geovista.common.utils.collection.CollectionUtils;
import edu.psu.geovista.ui.event.SelectionEvent;
import edu.psu.geovista.ui.event.SelectionListener;
import org.apache.commons.collections.map.ListOrderedMap;

import javax.swing.*;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class MyTable extends JTable {
    Map Id2Index;
    Map<Object, Set> dataGroups =new ListOrderedMap();
    String columnName_ID="ID";
     protected int IdColumnIndex = 0;
    boolean fireSelectionEvents=true;
    protected EventListenerList listenerList = new EventListenerList();

     public void setData(Object[] data){
        MyTableModel cmodel=new MyTableModel();
        cmodel.feedData(data);

        DefaultTableModel tableModel = MyTableModel.getTableModel(cmodel);
        this.setModel(tableModel);
    }
     public  void fireSelectionChanged (int[] lowLevelSelection) {

        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();
        SelectionEvent e = null;
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == SelectionListener.class) {
                // Lazily create the event:
                if (e == null) {
                    e=new SelectionEvent(this, lowLevelSelection);
                }
                ((SelectionListener)listeners[i + 1]).selectionChanged(e);
            }
        }//next i
     }

    /**
        * adds an SelectionListener
        */
       public void addSelectionListener (SelectionListener l) {
          listenerList.add(SelectionListener.class, l);
       }

       /**
        * removes an SelectionListener from the component
        */
       public void removeSelectionListener (SelectionListener l) {
           listenerList.remove(SelectionListener.class, l);
       }
         public void setId2IndexMap(Map<Object, Integer> id2Index) {
        this.Id2Index = id2Index;
    }

    public int[] getSelDataIndexs() {
        int[] sel = getSelectedRows();
        return getSelDatatIndexs(sel);
    }

    /**
     *
     * @param selrows
     * @return
     */
    public  int[] getSelDatatIndexs(int[] selrows) {
        Set selectedIds = this.getSelectedId(selrows);
        int[] selectedDataindex = getSelCDataIndex(selectedIds);
        return selectedDataindex;
    }
   public  int[] getSelCDataIndex(Set ids){
       Set dataIndexs=new HashSet();
        for (Iterator iterator = ids.iterator(); iterator.hasNext();) {
            Object groupId = (Object) iterator.next();
            Set mbrIds = dataGroups.get(groupId) ;
            for (Iterator iterator1 = mbrIds.iterator(); iterator1.hasNext();) {
                Object id = (Object) iterator1.next();
                Integer dataIndex =null;
                if(Id2Index!=null){

                     dataIndex = (Integer) Id2Index.get(id);
    
                }
                if(dataIndex==null)  {

                    String msg = "Unexpected error:" +this.getClass().getName() + " data id " + id + " find no data index " + dataIndex;
                    JOptionPane.showMessageDialog(null,msg);
                    break;
                    //System.err.println(msg);
                }
                if(dataIndex!=null)
                dataIndexs.add(dataIndex);

            }
        }
        int[] dataindexs = CollectionUtils.convert2IntArray(dataIndexs);
        return dataindexs;
    }
    /**
     *
     * @param selectedDataIds
     * @return
     */
     public  int[] getSelectedDataIndex(Set selectedDataIds){
       Set dataIndexs=new HashSet();
        for (Iterator iterator = selectedDataIds.iterator(); iterator.hasNext();) {
            Object id = (Object) iterator.next();
            Integer dataIndex = (Integer) Id2Index.get(id);
            dataIndexs.add(dataIndex);
        }
        int[] dataindexs = VitUtils.convert2IntArray(dataIndexs);
        return dataindexs;
    }
   public void valueChanged(ListSelectionEvent e) {
        super.valueChanged(e);
        if(isFireSelectionEvents() ){
        fireSelection();
        }
    }

    /**
     *
     * @param selectedRows
     * @return    selected
     */
    public  Set getSelectedId(int[] selectedRows){
        TableColumn tableColumn = getColumn(columnName_ID);
        int columnIndex = tableColumn.getModelIndex();
        //Set dataIndexs=new HashSet();
        Set ids=new HashSet();
        Object id =null;
        for (int i=0;i<selectedRows.length ;i++){
            int row = selectedRows[i];  //selected row
            id = getValueAt(row, columnIndex); // selected location/cluster ID display on the table
            ids.add(id);

        }
        return ids;
    }
     public int[] getRowIndexsByIDs(Set myIds) {
        int idColIndex = this.getIDColumnIndex();
        Object[] allIds = this.getColumnValues(idColIndex);
        Set indexs = new HashSet();
        for (int row = 0; row < allIds.length; row++) {
            if (myIds.contains(allIds[row])) {
                indexs.add(row);
            }
        }
        return VitUtils.convert2IntArray(indexs);//id not found in ID column
    }
    public Object[] getColumnValues(int col) {
           if (col < 0) {
               return new Object[0];
           }
           TableModel model = dataModel;
           int rowCount = model.getRowCount();
           Object[] cols = new Object[rowCount];
           for (int i = 0; i < rowCount; i++) {
               cols[i] = model.getValueAt(i, col);
           }
           return cols;
       }
      public void selectRows(int[] selectedRows)
	{
	    //table.setSelectionMode(2);
		if (selectedRows == null){
		    return;
		}
        this.setFireSelectionEvents(false);
        int len = selectedRows.length;
        selectRow(selectedRows[0]);  //To clear previously selection
	    for (int i = 1 ; i<len ; i++){
            
             addSelectedRow(selectedRows[i]) ;
        }
	    repaint() ;
        this.setFireSelectionEvents(true);
        this.fireSelection();
    }
     public void selectRow(int rowIndex) {
        this.setColumnSelectionInterval(0, this.getColumnCount() - 1);
        this.setRowSelectionInterval(rowIndex, rowIndex);

    }
    public void addSelectedRow(int rowIndex) {
           addRowSelectionInterval(rowIndex, rowIndex);
           setColumnSelectionInterval(0, getColumnCount() - 1);

       }

    public   void fireSelection() {
        int[] selectedDataindex = getSelDataIndexs();
        System.out.println(this.getClass().getSimpleName() +".valueChanged() my fireSelection: "+selectedDataindex.length );
        fireSelectionChanged(selectedDataindex);
    }
     public void setColumnName_ID(String columnName_ID) {
        this.columnName_ID = columnName_ID;
    }
     public void setDataGroups( Map<Object, Set> dataGroups) {
        this.dataGroups = dataGroups;
    }

    public boolean isFireSelectionEvents() {
        return fireSelectionEvents;
    }

    public void setFireSelectionEvents(boolean fireSelectionEvents) {
        this.fireSelectionEvents = fireSelectionEvents;
    }
    public int getIDColumnIndex() {
        return IdColumnIndex;
    }

   
    public void setIDColumnIndex(int index) {
        this.IdColumnIndex = index;

    }
}
